#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>
using namespace std;

#define SEP " "
#define SEP_LEN strlen(SEP)
#define SEP_LINE "\r\n"
#define SEP_LINE_LEN strlen(SEP_LINE)

enum
{
    OK = 0,
    DIV_ERROR,  // /0错误
    MOD_ERROR,  //%0错误
    OP_ERROR // 操作符错误
};

//去掉报文 "context_len\r\nx op y\r\n" -> "x op y"
bool deLength(const string& in,string* out)
{
    auto pos = in.find(SEP_LINE);
    if(pos == string::npos) return false;
    string text_string_len = in.substr(0,pos);
    int text_len = stoi(text_string_len); // 这里是文本的长度
    *out = in.substr(pos+SEP_LINE_LEN,text_len);
    return true;
}


//加报文 "x op y" ->"context_len\r\nx op y\r\n"
bool enLength(const string& str,string* text)
{
    int context_len = str.size();
    string context_len_string = to_string(context_len);
    *text += context_len_string;
    *text += SEP_LINE;
    *text += str;
    *text += SEP_LINE;
    return true;
}


//我们这里就是简单的计算逻辑的业务
class Request
{
public:
    Request()
    {}
    Request(int x,int y,int op)
    :_x(x),_y(y),_op(op)
    {}
    //序列化
    bool serialize(string* out)
    {
#ifdef MYSELF
        //结构化对象转换成字符串 "x op y"
        string x_string = to_string(_x);
        string y_string = to_string(_y);
        *out += x_string;
        *out += SEP;
        *out += _op;
        *out += SEP;
        *out += y_string;
#else
        Json::Value root;
        root["first"] = _x;
        root["second"] = _y;
        root["oper"] = _op;
        Json::FastWriter writer;
        *out = writer.write(root);
#endif
        return true;
    }
    //反序列化
    //"x op y"
    bool deserialize(const string& in)
    {
#ifdef MYSELF
        int left = in.find(SEP);
        int right = in.rfind(SEP);
        if(left == string::npos || right == string::npos)   return false;
        if(right == left)   return false;
        if(right - (left+SEP_LEN) != 1) return false;
        string x_string = in.substr(0,left);
        string y_string = in.substr(right+SEP_LEN);
        if(x_string.empty() || y_string.empty())    return false;
        _x = stoi(x_string);
        _y = stoi(y_string);
        _op = in[left+SEP_LEN];
#else
        Json::Value root;
        Json::Reader read;
        read.parse(in,root); // 把我们的字符串反序列化好放入root中
        _x = root["first"].asInt();
        _y = root["second"].asInt();
        _op = root["oper"].asInt();
#endif
        return true;
    }
    ~Request()
    {}
public:
    int _x;
    int _y;
    int _op;
};


class Response
{
public:
    Response()
    {}
    Response(int exitcode,int result)
    :_exitcode(exitcode),_result(result)
    {}
    //序列化
    //"exitcode result"
    bool serialize(string* out)
    {
#ifdef MYSELF
        string exitcode = to_string(_exitcode);
        string result = to_string(_result);
        *out += exitcode;
        *out += SEP;
        *out += result;
#else
        Json::Value root;
        root["exitcode"] = _exitcode;
        root["result"] = _result;
        Json::FastWriter writer;
        *out = writer.write(root);
#endif
        return true;
    }
    //反序列化
    bool deserialize(const string& in)
    {
#ifdef MYSELF
        //"exit_code result"
        auto pos = in.find(SEP);
        string exit_code = in.substr(0,pos);
        string result = in.substr(pos+SEP_LEN);
        _exitcode = stoi(exit_code);
        _result = stoi(result);
#else
        Json::Value root;
        Json::Reader read;
        read.parse(in,root);
        _exitcode = root["exitcode"].asInt();
        _result = root["result"].asInt();
#endif
        return true;
    }
    ~Response()
    {}
public:
    int _exitcode; //退出码，防止除0，或者模0错误
    int _result; //结果
};


// "context_len\r\nx op y\r\n" "context_len\r\nx op y\r\n"报文格式 --协议
bool recvPackage(int sock,string& inbuffer,string* out)
{
    while(true)
    {
        //接收
        char buffer[1024];
        int n = recv(sock,buffer,sizeof(buffer),0);
        if(n > 0)
        {
            buffer[n] = 0; 
            inbuffer += buffer; // 把结果都放到这里，因为有tcp传输是字节流的，可能一次传过来的不是一份完成的报文
            auto pos = inbuffer.find(SEP_LINE);
            if(pos == string::npos) continue; //这里没有找到可能是对方还没有发送过来
            string text_string_len = inbuffer.substr(0,pos);  //[left,right) len = right-left
            int text_len = stoi(text_string_len); 
            int total_len = text_string_len.size() + text_len + 2*SEP_LINE_LEN; //这里计算出总长度，方便我们确定一个完整的数据报
            if(inbuffer.size() < total_len)
            {
                //这里还没有完整的数据报
                cout<<"还没有收到完整的信息，请继续输入"<<endl;
                continue;
            }
            //到这里一定是拿到了一个完整的数据报了
            *out = inbuffer.substr(0,total_len);
            inbuffer.erase(0,total_len);
            break;
        }
        else{
            //这里说明接收错误，就玩不了了
            return false;
        }
    }
    return true;
}